home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-01-14 | 31.4 KB | 1,112 lines | [TEXT/KAHL] |
- /* Functions for doing things to windows. Included are functions for validating
- a window, accessing and setting common window fields (to avoid directly
- referencing fields in a window record), positioning a window according
- to the Human Interface Notes (HIN), saving and restoring a window's
- position, creating and disposing of a window, and various other
- miscelanous functions. A window created by this library also has some
- extra fields added to it which support proper positioning, zooming,
- and saving/restoring the window's position.
-
- Also supported are multiple window layers, including floating windoids.
- Currently, there are three layers: the regular document layer, a
- floating windoid layer, and a modal dialog layer. Document windows
- always fall behind any floating windows, and floating windows always
- fall behind any modal windows. System windows can come in front of
- any window layer, but normally can not be selected when a modal dialog
- is front most (since that would violate the HIG). Window layers are
- assigned automatically when a window is created based on its procID.
- Window layers would have been simpler to implement if there was some
- way to disable the generation of activate events for certain windows,
- to disable automatic window hiliting (automatic window hiliting is
- disabled using a patch), and to ignore system windows. Much of the
- complexity of window layers is due solely to system windows. System
- windows can be ignored under MultiFinder, but under Finder they must
- be accommadated.
-
- Notice: The window positioning and zooming functions have been moved to
- separate files.
-
- Revision History:
-
- 94/01/08 aih
- - added function to determine if a window is entirely visible, and
- added a postcondition to WinShow that ensures that a window is properly
- positioned
- - moved several window positioning and sizing related functions to
- WindowPositionLib.c
- - strengthened a few pre- and postconditions
-
- 93/12/16 aih
- - added some comments
-
- 93/12/07 aih
- - added support for my windoid WDEF's variation codes
-
- 93/12/02 aih
- - changed function for dragging windows to use a library function of mine
- rather than DragGrayRgn
-
- 93/12/01 aih
- - improved calculation of structure and content rectangles for invisible
- windows
- - improved calculation of rectangle for new windows
- - improved zoom functions (a few days ago)
-
- 93/11/15 aih
- - continuing development of window layers to work properly with system
- windows
- - drag outline for a window is clipped to the windows above it
- - if in pre-7.0 system and using a movable modal dialog then
- a special WDEF (released by MacDTS) is substituted for WDEF 0.
- - improved dialog creation code
- - program_note: the functions that use GetWVariant to determine window
- characteristics won't work with windows that don't
- use the standard variants or variants I've programmed
- in for them.
-
- 93/11/12 aih
- - added window layers (again...)
-
- 93/11/03 aih
- - the extra window information is stored in a handle instead of a pointer
-
- 93/10/25 aih
- - removed unused functions
-
- 93/03/14 AIH
- - Removed most of window layer code since it just wasn't working
-
- 93/03/06 AIH
- - A check-mark is placed next to the current window
-
- 93/03/05 AIH
- - Added functions for hiding a window, activating/deactiving all windows
- in a layer (especially useful when displaying modal dialogs and when
- suspending and resuming the application)
-
- 92/05/24 AIH
- - Fixed some problems with floating windows
-
- 92/03/06 AIH
- - Added support for multiple window layers, such as document
- and pallete windows
-
- 92/03/02 AIH
- - Changed extra window data into a pointer which is saved in
- the window's refCon field. This simplified a lot of the code.
- Thanks goodness for data hiding! It made modifying this
- library a breeze.
-
- 92/03/01 AIH
- - Got rid of unused window kinds
-
- 92/02/26 AIH
- - Added function to determine if the front window is modal
- - Added function to determine if a window has a go away box
- - Added tab object list
-
- 92/02/21 AIH
- - New windows are registered with the event library and unregistered
- when destroyed
-
- 91/07/03 AIH
- - Clarified a few comments
- - The window validation function accepts a flag to indicate if the window
- has to have been created by this library
-
- 91/06/13 AIH
- - Added functions for getting the first window in the window list
- and the first visible window in the window list. These may be adapted
- in the future to support floating windows.
- - Changed name of the function "WinRect" to better describe its purpose
-
- 91/06/01 AIH
- - A color window is created from a window template if the Macintosh supports
- color
- - The window's size rectangle is initialized when a window is created
- - Added function to handle setting a window's zoom state given a prefered
- size for the window
-
- 91/05/29 AIH
- - Added a constant size option to the window staggering function
-
- 91/05/28 AIH
- - A color window is created if the machine supports color
-
- 91/05/19-20 AIH
- - The staggering algorithm is more elegant
-
- 91/05/18 AIH
- - Fixed a mistake in the stagger window function
-
- 91/05/14 AIH
- - Still working on getting window states to be remembered correctly
-
- 91/05/12 AIH
- - The current screen is used, instead of just the main screen
- - Window size and position are remembered and set more in accordance
- with the HIN
- - Added function to stagger a window
-
- 91/05/09 AIH
- - Added a function for determining if a window is an event window
- - Added function to return next window in window list
-
- 91/05/07 AIH
- - To avoid drawing the grow icon twice when an activate event
- is followed by an update event we validate the grow icon's rectangle
- after it is drawn.
-
- 91/04/26 AIH
- - Added zoomDocProc to list of windows with drag regions, and added a
- function to determine if a window has a grow region
- - Added functions for saving and restoring window states
-
- 91/04/10 AIH
- - Added some "standard" window kinds
-
- 91/04/07 AIH
- - Added function to determine if a window needs updating
-
- 91/03/26 AIH
- - Got rid of WIN_MODAL_KIND since it wasn't needed and only complicated
- the code
- - Got rid of WIN_MOVABLE_MODAL since it has the (obvious) official
- name "movableDBoxProc"
-
- 91/03/23 AIH
- - Added function to return a window's position (from EventLib)
- - Added function to determine if a window can be dragged (from DialogLib)
-
- 91/03/14 AIH
- - Added function to draw the grow icon
-
- 91/03/10 Ari Halberstadt (AIH)
- - Created this library */
-
- #include <string.h>
- #include <stdlib.h>
- #include "DrawLib.h"
- #include "LowMemLib.h"
- #include "MacLib.h"
- #include "MemoryLib.h"
- #include "PatchLib.h"
- #include "RectangleLib.h"
- #include "ResourceConstantsLib.h"
- #include "ResourceLib.h"
- #include "ScreenLib.h"
- #include "StringLib.h"
- #include "SystemWindowLib.h"
- #include "WindoidWDEF.h"
- #include "WindowLib.h"
-
- static WindowPtr gLayers[WIN_LAYER_LAST]; /* lists of windows in each layer */
- static PatchType *gPatchHiliteWindow; /* data for patch to HiliteWindow */
-
- /*----------------------------------------------------------------------------*/
- /* window validation */
- /*----------------------------------------------------------------------------*/
-
- /* true if valid window layer */
- static Boolean WinLayerValid(WindowLayerType layer)
- {
- return(WIN_LAYER_NONE < layer && layer < WIN_LAYER_LAST);
- }
-
- /* true if window is a valid window */
- Boolean WinValid(WindowPtr window)
- {
- if (! MemValid(window)) return(false);
- if (((WindowPeek)window)->windowKind <= userKind) return(true);
- if (! PtrValidSize(window, sizeof(WindowRecord))) return(false);
- return(true);
- }
-
- /*----------------------------------------------------------------------------*/
- /* extra data */
- /*----------------------------------------------------------------------------*/
-
- /* return handle to extra window data */
- WindowExtraHandle WinExtraHandle(WindowPtr window)
- {
- WindowExtraHandle extra = NULL;
-
- require(WinKind(window) >= WIN_KIND_EXTRA);
- extra = (WindowExtraHandle) GetWRefCon(window);
- ensure(HandleValidSize(extra, sizeof(WindowExtraType)));
- return(extra);
- }
-
- /* Return pointer to extra window data. Warning: pointer is
- dereferenced handle, memory may move! */
- WindowExtraPtr WinExtraPtr(WindowPtr window)
- {
- return(*WinExtraHandle(window));
- }
-
- /* set the window's extra data */
- static void WinExtraSet(WindowPtr window, WindowExtraHandle extra)
- {
- require(WinKind(window) >= WIN_KIND_EXTRA);
- (**extra).window = window;
- SetWRefCon(window, (long) extra);
- ensure(WinValid(window));
- }
-
- /*----------------------------------------------------------------------------*/
- /* application defined data */
- /*----------------------------------------------------------------------------*/
-
- void *WinData(WindowPtr window)
- {
- return(WinExtraPtr(window)->data);
- }
-
- void WinDataSet(WindowPtr window, void *data)
- {
- WinExtraPtr(window)->data = data;
- }
-
- /*----------------------------------------------------------------------------*/
- /* window properties and attributes */
- /*----------------------------------------------------------------------------*/
-
- /* true if the window is visible */
- Boolean WinVisible(WindowPtr window)
- {
- require(WinValid(window));
- return(((WindowPeek)window)->visible != 0);
- }
-
- /* true if the entire window is visible */
- Boolean WinVisibleFully(WindowPtr window)
- {
- RgnHandle structureRgn;
- Boolean result = false;
-
- if (WinVisible(window)) {
- structureRgn = BeginRgn();
- CopyRgn(((WindowPeek) window)->strucRgn, structureRgn);
- SectRgn(GetGrayRgn(), structureRgn, structureRgn);
- result = EqualRgn(((WindowPeek) window)->strucRgn, structureRgn);
- EndRgn(structureRgn);
- }
- return(result);
- }
-
- /* return the window's windowKind field */
- short WinKind(WindowPtr window)
- {
- require(WinValid(window));
- return(((WindowPeek)window)->windowKind);
- }
-
- /* set the window's windowKind field */
- void WinKindSet(WindowPtr window, short kind)
- {
- require(WinValid(window));
- ((WindowPeek)window)->windowKind = kind;
- }
-
- /* true if window is a system window */
- Boolean WinIsSystem(WindowPtr window)
- {
- require(WinValid(window));
- return(WinKind(window) < 0);
- }
-
- /* true if window is a dialog window */
- Boolean WinIsDialog(WindowPtr window)
- {
- require(WinValid(window));
- return(WinKind(window) == dialogKind ||
- (WinHasExtra(window) && WinExtraPtr(window)->dialog));
- }
-
- /* true if window is a user window */
- Boolean WinIsUser(WindowPtr window)
- {
- require(WinValid(window));
- return(WinKind(window) >= userKind);
- }
-
- /* true if window is a floating window */
- Boolean WinIsFloat(WindowPtr window)
- {
- return(WinHasExtra(window) && WinLayer(window) == WIN_LAYER_FLOAT);
- }
-
- /* true if window is modal */
- Boolean WinIsModal(WindowPtr window)
- {
- Boolean result = false;
-
- require(WinValid(window));
- if (! WinIsFloat(window)) {
- switch (GetWVariant(window)) {
- case dBoxProc:
- case movableDBoxProc:
- result = true;
- break;
- }
- }
- return(result);
- }
-
- /* true a modal window has the input focus, or if the front window
- is a modal window (e.g., a standard file dialog) */
- Boolean WinModalHasFocus(void)
- {
- return((FocusWindow() && WinIsModal(FocusWindow())) ||
- (FrontWindow() && WinIsModal(FrontWindow())));
- }
-
- /* true if the window has extra information */
- Boolean WinHasExtra(WindowPtr window)
- {
- return(WinKind(window) >= WIN_KIND_EXTRA && WinExtraHandle(window) != NULL);
- }
-
- /* true if the window has a go away box */
- Boolean WinHasGoAway(WindowPtr window)
- {
- require(WinValid(window));
- return(((WindowPeek) window)->goAwayFlag);
- }
-
- /* true if window has a grow region */
- Boolean WinHasGrow(WindowPtr window)
- {
- Boolean result = false;
-
- require(WinValid(window));
- if (WinIsFloat(window))
- result = WindoidHasGrow(window);
- else switch(GetWVariant(window)) {
- case documentProc:
- case zoomDocProc:
- result = true;
- break;
- }
- return(result);
- }
-
- /* true if window can be dragged */
- Boolean WinHasDrag(WindowPtr window)
- {
- Boolean result = false;
-
- require(WinValid(window));
- if (WinIsFloat(window))
- result = WindoidHasDrag(window);
- else switch (GetWVariant(window)) {
- case documentProc:
- case noGrowDocProc:
- case zoomDocProc:
- case zoomNoGrow:
- case rDocProc:
- case movableDBoxProc:
- result = true;
- break;
- }
- return(result);
- }
-
- /* true if window can be zoomed */
- Boolean WinHasZoom(WindowPtr window)
- {
- Boolean result = false;
-
- require(WinValid(window));
- if (WinIsFloat(window))
- result = WindoidHasZoom(window);
- else switch (GetWVariant(window)) {
- case zoomDocProc:
- case zoomNoGrow:
- result = true;
- break;
- }
- return(result);
- }
-
- /* true if the window has the input focus */
- Boolean WinHasFocus(WindowPtr window)
- {
- return(window && window == FocusWindow());
- }
-
- /* get window's title */
- void WinTitle(WindowPtr window, CStr255 title)
- {
- require(WinValid(window));
- require(StrValid(title, -1));
- GetWTitle(window, (StringPtr) title);
- p2cstr((StringPtr) title);
- ensure(StrValid(title, sizeof(CStr255)));
- }
-
- /* set window's title */
- void WinTitleSet(WindowPtr window, const char *title)
- {
- Str255 ptitle;
-
- require(WinValid(window));
- require(StrValid(title, sizeof(CStr255)));
- c2pstr(strcpy((char*)ptitle, title));
- SetWTitle(window, ptitle);
- }
-
- /*----------------------------------------------------------------------------*/
- /* window layers */
- /*----------------------------------------------------------------------------*/
-
- /* return window's extra data */
- static WindowExtraHandle winextra(WindowPtr window)
- {
- return(window ? WinExtraHandle(window) : NULL);
- }
-
- /* return next window in list */
- static WindowPtr winnext(WindowPtr window)
- {
- WindowExtraHandle next = LLHNext(winextra(window));
- return(next ? (**next).window : NULL);
- }
-
- /* remove window from list */
- static WindowPtr windelete(WindowPtr head, WindowPtr item)
- {
- WindowExtraHandle list = LLHDelete(winextra(head), winextra(item));
- return(list ? (**list).window : NULL);
- }
-
- /* insert window into list */
- static WindowPtr wininsert(WindowPtr head, WindowPtr item)
- {
- WindowExtraHandle list = LLHInsert(winextra(head), winextra(item));
- return(list ? (**list).window : NULL);
- }
-
- /* return window's layer */
- WindowLayerType WinLayer(WindowPtr window)
- {
- return(WinExtraPtr(window)->layer);
- }
-
- /* set window's layer */
- void WinLayerSet(WindowPtr window, WindowLayerType layer)
- {
- WindowLayerType oldlayer = WinLayer(window);
-
- require(WinLayerValid(layer));
- gLayers[oldlayer] = windelete(gLayers[oldlayer], window);
- WinExtraPtr(window)->layer = layer;
- if (layer == WIN_LAYER_FLOAT)
- WinHilite(window, true);
- WinSelect(window);
- }
-
- /*----------------------------------------------------------------------------*/
- /* Accessing the list of windows. These functions use our own private
- array of window lists, in which each entry corresponds to a
- window layer. */
- /*----------------------------------------------------------------------------*/
-
- /* return first window in layer */
- WindowPtr WinFirst(WindowLayerType layer)
- {
- require(WinLayerValid(layer));
- return(gLayers[layer]);
- }
-
- /* return first visible window in layer */
- WindowPtr WinFirstVisible(WindowLayerType layer)
- {
- WindowPtr window = NULL;
-
- require(WinLayerValid(layer));
- window = WinFirst(layer);
- while (window && ! WinVisible(window))
- window = WinNext(window);
- ensure(! window || WinVisible(window));
- return(window);
- }
-
- /* return next window in window's layer */
- WindowPtr WinNext(WindowPtr window)
- {
- return(winnext(window));
- }
-
- /* return next visible window in window's layer */
- WindowPtr WinNextVisible(WindowPtr window)
- {
- do {
- window = WinNext(window);
- } while (window && ! WinVisible(window));
- ensure(! window || WinVisible(window));
- return(window);
- }
-
- /* return the first visible non-floating window */
- WindowPtr WinFirstVisibleNonFloat(void)
- {
- const WindowLayerType skip = WIN_LAYER_FLOAT;
- WindowLayerType layer = WIN_LAYER_NONE;
- WindowPtr window = NULL;
-
- for (layer = WIN_LAYER_LAST-1; ! window && layer >= WIN_LAYER_FIRST; --layer)
- if (layer != skip)
- window = WinFirstVisible(layer);
- ensure(! window ||
- (window == WinFirstVisible(WinLayer(window)) && ! WinIsFloat(window)));
- return(window);
- }
-
- /* return the next visible non-floating window */
- WindowPtr WinNextVisibleNonFloat(WindowPtr window)
- {
- const WindowLayerType skip = WIN_LAYER_FLOAT;
- WindowLayerType layer = WinLayer(window);
-
- if (layer == skip)
- window = NULL;
- else
- window = WinNextVisible(window);
- while (! window && layer >= WIN_LAYER_FIRST) {
- if (layer != skip)
- window = WinFirstVisible(layer);
- --layer;
- }
- ensure(! window || (WinVisible(window) && ! WinIsFloat(window)));
- return(window);
- }
-
- /*----------------------------------------------------------------------------*/
- /* displaying and selecting */
- /*----------------------------------------------------------------------------*/
-
- /* return the window that a window should be sent behind of so as
- to be the first window in the layer, or NULL if should be in front
- of all other windows */
- static WindowPtr WinGetBehind(WindowLayerType layer)
- {
- WindowLayerType nextlayer = layer + 1;
- WindowPtr behind = NULL;
-
- require(WinLayerValid(layer));
- while (nextlayer < WIN_LAYER_LAST && ! WinFirstVisible(nextlayer))
- nextlayer++;
- if (nextlayer < WIN_LAYER_LAST) {
- behind = WinFirstVisible(nextlayer);
- while (WinNextVisible(behind))
- behind = WinNextVisible(behind);
- }
- ensure(! behind || WinValid(behind));
- return(behind);
- }
-
- /* send window behind another window */
- static void WinSendBehind(WindowPtr window, WindowPtr behind)
- {
- RgnHandle exposedRgn;
- WindowPeek wpeek = (WindowPeek) window;
- WindowPeek win = NULL;
-
- require(WinValid(window));
- require(! behind || WinVisible(behind));
- require(window != behind);
- exposedRgn = BeginRgn();
- if (behind) {
- win = wpeek->nextWindow;
- while (win && win != (WindowPeek) behind)
- win = win->nextWindow;
- }
- if (behind && ! win) /* moving window closer */
- CopyRgn(window->visRgn, exposedRgn);
- SendBehind(window, behind);
- if (behind && ! win) {
- /* Moved window closer. IM-I p286 recommends using:
- PaintOne(wpeek, wpeek->strucRgn);
- CalcVis(wpeek);
- but that doesn't work well since the entire window's
- content region is redrawn even though only the newly
- exposed region needs redrawing. Also, the visRgn's
- of the windows behind the window aren't updated
- correctly. So, we use the following calls to
- update the windows. */
- PortToGlobalRgn(exposedRgn, window);
- DiffRgn(wpeek->strucRgn, exposedRgn, exposedRgn);
- PaintOne(wpeek, exposedRgn);
- CalcVisBehind(wpeek, wpeek->strucRgn);
- }
- EndRgn(exposedRgn);
- }
-
- /* prevent hiliting of our windows by the window manager */
- static pascal void PatchHiliteWindow(PatchType *patch, WindowPtr window, Boolean hilite)
- {
- patch->skip = (((WindowPeek) window)->windowKind >= WIN_KIND_EXTRA);
- }
-
- /* hilite the window */
- void WinHilite(WindowPtr window, Boolean hilite)
- {
- PatchRemove(gPatchHiliteWindow);
- HiliteWindow(window, hilite);
- PatchInstall(gPatchHiliteWindow);
- }
-
- /* move window to front of its layer */
- static void DoWinSelect(WindowPtr activate, WindowPtr const deactivate)
- {
- WindowLayerType layer = WinLayer(activate);
- WindowPtr behind = NULL;
-
- require(WinValid(activate));
- require(! deactivate ||
- (! WinIsFloat(deactivate) &&
- (deactivate == FocusWindow() || WinIsSystem(deactivate))));
-
- /* program_note: should really be a precondition, but it's ok since
- winshow selects the window; this is a temporary work-around till
- i figure out how to get WinSendBehind to work with invisible
- windows */
- if (! WinVisible(activate)) return;
-
- /* make the window be the first window in its layer */
- behind = WinGetBehind(layer);
- if (behind && (WindowPtr)((WindowPeek)behind)->nextWindow != activate)
- WinSendBehind(activate, behind);
- else if (! behind && FrontWindow() != activate)
- BringToFront(activate);
- if (activate != WinFirst(layer))
- gLayers[layer] = wininsert(windelete(gLayers[layer], activate), activate);
-
- check(activate == WinFirst(layer));
-
- if (WinVisible(activate)) {
-
- /* pass activate event to first non-floating window */
- if (WinIsFloat(activate))
- activate = WinNextVisibleNonFloat(activate);
-
- /* send system windows behind selected window */
- if (deactivate && WinIsSystem(deactivate)) {
- WindowPtr behind = activate;
- WindowPtr system = deactivate;
- HiliteWindow(deactivate, false);
- while (system && WinIsSystem(system)) {
- WindowPtr next = (WindowPtr) ((WindowPeek) system)->nextWindow;
- WinSendBehind(system, behind);
- behind = system;
- system = next;
- }
- }
-
- /* Suppress activate event if a window has the input focus and it is
- in a layer above the window that would be activated. This suppresses
- the activate event, for instance, that would be generated for a
- document window when a modal dialog is front most and the document
- window is created behind it. */
- if (activate && FocusWindow() && WinLayer(FocusWindow()) > WinLayer(activate))
- activate = NULL;
-
- /* post activate events */
- if (activate && activate != FocusWindow()) {
- SetCurActivate(activate);
- SetCurDeactive(deactivate);
- }
- }
- }
-
- /* move window to front of its layer */
- void WinSelect(WindowPtr window)
- {
- DoWinSelect(window, FocusWindow() ? FocusWindow() : SystemWindowActive());
- }
-
- /* make the window invisible */
- void WinHide(WindowPtr window)
- {
- WindowPtr activate = NULL;
-
- require(WinValid(window));
- if (WinVisible(window)) {
- ShowHide(window, false);
- if (window == FocusWindow()) {
- activate = SystemWindowActive();
- if (! activate)
- activate = WinNextVisibleNonFloat(window);
- if (! activate || WinIsSystem(activate)) {
- if (activate)
- HiliteWindow(activate, true);
- FocusWindowSet(NULL);
- EventAdjustMenu();
- }
- else
- FocusWindowSet(activate);
- SetCurActivate(activate);
- SetCurDeactive(NULL);
- }
- }
- ensure(! WinVisible(window));
- }
-
- /* make the window visible and select it */
- void WinShow(WindowPtr window)
- {
- require(WinValid(window));
- if (! WinVisible(window)) {
- WindowPtr deactivate = FocusWindow() ? FocusWindow() : SystemWindowActive();
- if (WinIsModal(window)) {
- WinHilite(window, true); /* prehiliting just looks better */
- HiliteMenu(0); /* prevent menu bar flicker */
- }
- ShowHide(window, true);
- DoWinSelect(window, deactivate);
- }
- ensure(WinVisible(window));
- ensure(! WinHasDrag(window) ? WinVisibleFully(window) : WinCanDrag(window));
- }
-
- /*----------------------------------------------------------------------------*/
- /* window rectangles */
- /*----------------------------------------------------------------------------*/
-
- /* get the window's port rectangle */
- void WinPortRect(WindowPtr window, Rect *r)
- {
- require(WinValid(window));
- *r = window->portRect;
- ensure(RectValid(r));
- }
-
- /* Get the bounding rectangles for several window structures. These are
- all merged into one function since calculating these rectangles for
- an invisible window involves many redundant and slow calculations.
- All rectangles are in global coordinates. */
- void WinRectangles(WindowPtr window,
- Rect *structureRect,
- Rect *contentRect,
- Rect *dragRect,
- Rect *newRect)
- {
- require(WinValid(window));
-
- /* structure and content regions are
- only valid if window is visible */
- if (! WinVisible(window)) {
- Point pt;
- Rect windBBox;
- Rect grayBBox;
- grayBBox = (**GetGrayRgn()).rgnBBox;
- WinPortRect(window, &windBBox);
- RectPortToGlobal(&windBBox, window);
- pt.h = grayBBox.left - RectWidth(&windBBox) - 512;
- pt.v = grayBBox.top - RectHeight(&windBBox) - 512;
- WinMove(window, pt.h, pt.v);
- ShowHide(window, true);
- *structureRect = (**((WindowPeek) window)->strucRgn).rgnBBox;
- *contentRect = (**((WindowPeek) window)->contRgn).rgnBBox;
- OffsetRect(structureRect, windBBox.left - pt.h, windBBox.top - pt.v);
- OffsetRect(contentRect, windBBox.left - pt.h, windBBox.top - pt.v);
- ShowHide(window, false);
- WinMove(window, windBBox.left, windBBox.top);
- }
- else {
- *structureRect = (**((WindowPeek) window)->strucRgn).rgnBBox;
- *contentRect = (**((WindowPeek) window)->contRgn).rgnBBox;
- }
-
- /* calculate drag rectangle (assumes adjacent to window, at least
- 5 pixels wide, and either on top or to left of window) */
- SetRect(dragRect, 0, 0, 0, 0);
- if (WinHasDrag(window)) {
- *dragRect = *structureRect;
- if (structureRect->top + 5 < contentRect->top)
- dragRect->bottom = contentRect->top; /* drag region above window */
- else if (structureRect->left + 5 < contentRect->left)
- dragRect->right = contentRect->left; /* drag region left of window */
- InsetRect(dragRect, 1, 1);
- }
-
- /* Calculate the largest rectangle (in global coordinates) for a new window.
- The rectangle is completely contained on the current screen, and
- excludes the menu bar, the window's title bar, and a few pixels from
- each edge of the screen. */
- ScreenGrayRect(newRect);
- InsetRect(newRect, SCREEN_MARGIN, SCREEN_MARGIN);
- newRect->top += contentRect->top - structureRect->top;
- newRect->left += contentRect->left - structureRect->left;
- newRect->bottom -= structureRect->bottom - contentRect->bottom;
- newRect->right -= structureRect->right - contentRect->right;
-
- ensure(RectValid(structureRect));
- ensure(RectValid(contentRect));
- ensure(RectValid(dragRect));
- ensure(RectValid(newRect));
- ensure(RectWithin(contentRect, structureRect));
- }
-
- void WinStructureRect(WindowPtr window, Rect *structure)
- {
- Rect content, drag, new;
- WinRectangles(window, structure, &content, &drag, &new);
- }
-
- void WinContentRect(WindowPtr window, Rect *content)
- {
- Rect structure, drag, new;
- WinRectangles(window, &structure, content, &drag, &new);
- }
-
- void WinDragRect(WindowPtr window, Rect *drag)
- {
- Rect structure, content, new;
- WinRectangles(window, &structure, &content, drag, &new);
- }
-
- void WinNewRect(WindowPtr window, Rect *new)
- {
- Rect structure, content, drag;
- WinRectangles(window, &structure, &content, &drag, new);
- }
-
- /*----------------------------------------------------------------------------*/
- /* window drawing */
- /*----------------------------------------------------------------------------*/
-
- /* This routine is similar to the Window Manager routine DrawGrowIcon,
- except that it does not draw the lines enclosing the scroll bars. */
- void WinDrawGrowIcon(WindowPtr window)
- {
- RgnHandle clip;
- Handle sicn = NULL;
- GrafPtr port= NULL;
- PenState pen;
- Rect grow;
- Point pt;
-
- require(WinValid(window));
- GetPort(&port);
- SetPort(window);
- GetPenState(&pen);
- PenNormal();
- clip = BeginRgn();
- GetClip(clip);
- WinPortRect(window, &grow);
- grow.left = grow.right - 15;
- grow.top = grow.bottom - 15;
- ClipRect(&grow);
- DrawGrowIcon(window);
- SetClip(clip);
- SetPenState(&pen);
- SetPort(port);
- EndRgn(clip);
- ensure(WinValid(window));
- }
-
- /*----------------------------------------------------------------------------*/
- /* window creation and destruction */
- /*----------------------------------------------------------------------------*/
-
- /* create the extra window data and register the window so it receives
- events */
- void WinInitialize(WindowPtr window, WindowLayerType layer)
- {
- WindowExtraHandle extra = NULL;
-
- require(! WinVisible(window));
- TRY {
- extra = HandleBeginClear(sizeof(WindowExtraType));
- if (WinKind(window) == dialogKind)
- (**extra).dialog = true;
- WinKindSet(window, WIN_KIND_EXTRA);
- WinExtraSet(window, extra);
- WinRegister(window, window, WinEventTable());
- WinLayerSet(window, layer);
- } CATCH {
- WinUninitialize(window);
- } ENDTRY;
- }
-
- /* unregister the window and dispose of the extra data */
- void WinUninitialize(WindowPtr window)
- {
- require(WinValid(window));
- if (WinHasExtra(window)) {
- gLayers[WinLayer(window)] = windelete(gLayers[WinLayer(window)], window);
- WinUnregister(window, window);
- check(WinExtraPtr(window)->objects == NULL);
- HandleEnd(WinExtraPtr(window)->tablist);
- HandleEnd(WinExtraHandle(window));
- SetWRefCon(window, 0L);
- }
- }
-
- /* Adjust the window template and return window behind which the
- window created based from the template should be sent. The new window's
- layer is returned in the 'layer' parameter. This function is used only
- before creating a window or dialog. */
- WindowPtr WinAdjustTemplate(WindowTemplate *wind, WindowLayerType *layer)
- {
- static Boolean installed; /* true if installed patch */
- WindowPtr behind = NULL; /* create window behind this window */
- short wdefID = 0; /* id of wdef */
- short varID = 0; /* window's variation code */
-
- /* install patch */
- if (! installed) {
- gPatchHiliteWindow =
- PatchBegin(PatchHiliteWindow, _HiliteWindow,
- sizeof(WindowPtr) + sizeof(PatchBooleanParameter), 0, NULL);
- installed = true;
- }
-
- /* determine window layer */
- wdefID = (wind->procID >> 4);
- varID = (wind->procID & 0x000F);
- if (wdefID == RLWDEF_FLOAT)
- *layer = WIN_LAYER_FLOAT;
- else if (varID == dBoxProc || varID == movableDBoxProc)
- *layer = WIN_LAYER_MODAL;
- else
- *layer = WIN_LAYER_DOCUMENT;
- behind = WinGetBehind(*layer);
- if (! behind)
- behind = (WindowPtr) -1L;
-
- /* for compatability with systems prior to 7.0, use special WDEF
- for movable modal dialogs */
- if (MacVersion() < 0x0700 && wind->procID == movableDBoxProc)
- wind->procID += RLWDEF_MOVABLE_MODAL * 16;
-
- return(behind);
- }
-
- /* create a new window from the window template */
- static WindowPtr WinBeginTemplate(WindowTemplate *wind)
- {
- WindowPtr behind = NULL; /* create window behind this window */
- WindowLayerType layer = 0; /* new window's layer */
- volatile WindowPtr window = NULL; /* the new window */
-
- require(RectValid(&wind->boundsRect));
- TRY {
- behind = WinAdjustTemplate(wind, &layer);
- MemCheck(sizeof(WindowRecord));
- if (MacHasColor()) {
- window = NewCWindow(NULL, &wind->boundsRect, wind->title, false,
- wind->procID, behind, wind->goAwayFlag, wind->refCon);
- }
- else {
- window = NewWindow(NULL, &wind->boundsRect, wind->title, false,
- wind->procID, behind, wind->goAwayFlag, wind->refCon);
- }
- FailNIL(window);
- WinInitialize(window, layer);
- } CATCH {
- WinEnd(window);
- } ENDTRY;
- ensure(! WinVisible(window));
- return(window);
- }
-
- /* create a new invisible window using the specified 'WIND' resource */
- WindowPtr WinGet(short id)
- {
- WindowTemplate wind;
-
- ResPtr('WIND', id, &wind, sizeof(WindowTemplate));
- return(WinBeginTemplate(&wind));
- }
-
- /* create a new invisible window */
- WindowPtr WinBegin(short procID, Boolean goAwayFlag)
- {
- WindowTemplate wind;
-
- memclr(&wind, sizeof(WindowTemplate));
- SetRect(&wind.boundsRect, 0, 0, 100, 100);
- wind.procID = procID;
- wind.goAwayFlag = goAwayFlag;
- return(WinBeginTemplate(&wind));
- }
-
- /* dispose of the window */
- void WinEnd(WindowPtr window)
- {
- if (window) {
- WinHide(window);
- WinUninitialize(window);
- DisposeWindow(window);
- window = NULL;
- }
- ensure(! WinValid(window));
- }
-
- /*----------------------------------------------------------------------------*/
- /* event handling */
- /*----------------------------------------------------------------------------*/
-
- /* activate/deactivate the window */
- void WinActivate(WindowPtr window, Boolean active)
- {
- require(WinValid(window));
- WinHilite(window, active);
- if (WinHasGrow(window))
- WinDrawGrowIcon(window);
- ensure(WinValid(window));
- }
-
- /* hide all windows in layer from back to front to minimize redrawing */
- static void WinHideLayer(WindowPtr window)
- {
- if (window) {
- WinHideLayer(WinNext(window));
- if (WinVisible(window))
- WinExtraPtr(window)->visible = true;
- else
- WinExtraPtr(window)->visible = false;
- ShowHide(window, false);
- }
- }
-
- /* show all windows in layer from front to back to minimize redrawing */
- static void WinShowLayer(WindowPtr window)
- {
- while (window) {
- if (WinExtraPtr(window)->visible)
- ShowHide(window, true);
- window = WinNext(window);
- }
- }
-
- /* handle suspend event */
- void WinSuspend(void)
- {
- WinHideLayer(WinFirst(WIN_LAYER_FLOAT));
- EventActivate(FocusWindow(), false);
- }
-
- /* handle resume event */
- void WinResume(void)
- {
- WinShowLayer(WinFirst(WIN_LAYER_FLOAT));
- EventActivate(FocusWindow(), true);
- }
-
- /* update the window */
- void WinUpdate(WindowPtr window)
- {
- require(WinValid(window));
- if (WinHasGrow(window))
- WinDrawGrowIcon(window);
- if (WinIsDialog(window))
- UpdtDialog(window, window->visRgn);
- else
- UpdtControl(window, window->visRgn);
- ensure(WinValid(window));
- }
-